13. Manage Resource with OOP

RAII(Resource Acquisition Is Initialization)
생산자 안에서 자원을 획득하고, 소멸자에서 해당 자원을 해제하는 객체
auto_ptr <memory>
auto_ptr은 C++17 이후 삭제됨
auto_ptr은 템플릿 기반으로 포인팅하는 객체가 스코프를 벗어나면 해당 객체의 소멸자를 호출한다.
auto_ptr은 하나의 소유권을 보장하기 위해서 auto_ptr로 포인팅한 객체가 복사되면, 원본 auto_ptr이
가르키는 포인팅 객체는 nullptr이 된다.

auto_ptr은 동적할당된 배열을 삭제시키지 않는다.(배열 단위 해제를 보장하지 않음)
현재는 unique_ptr이 이를 대체함 unique_ptr<T, Deleter>
(unique_ptr은 std::move를 이용해서 소유권을 이전함, 복사 생성자, 복사 대입 연산자 지원X)

하지만, auto_ptr은 new로 생성한(동적할당) 객체에 대해서만 메모리 해제를 보장한다.
(malloc 등으로 할당한 경우, 해제가 되지 않음 new-delete로 생성된 메모리만 사용가능)
malloc-free & new-delete
malloc은 반환값이 (void*) 형이기 때문에 아래와 같이 타입 변환을 해 주어야 한다.
new는 type-safe로 컴파일러가 타입형을 확인해 준다.
new는 객체를 생성하면서 초기값을 설정할 수 있다.(malloc은 초기화 기능이 없음, memset을 별도로 사용)
new는 에러가 발생하면 예외처리를 하지만, malloc은 NULL을 반환한다.
malloc은 realloc을 사용해서 메모리 크기를 재조정할 수 있지만, new는 메모리 조정이 불가능함

delete는 소멸자를 호출한다.(free는 소멸자 호출기능이 없다)
int* i=(int*)malloc(sizeof(int));
int a=new a(5);
복사 연산자를 지원하지 않는 auto_ptr의 특징 때문에 STL 컨테이너를 사용할 때,
shared_ptr을 사용할 수 있다.
class Investment{ /* ... */ };
Investment* createInvestment(void); //
// .
void f(void){
// ...
std::shared_ptr<Investment> pInv1(createInvestment());
std::shared_ptr<Investment> pInv2(pInv1);
pInv1=pInv2;
// ...
} // ,
스마트 포인터는 내부적으로 소멸자를 호출할 때, delete를 사용한다.
(delete[]를 사용하지 않음)
따라서 동적 배열을 사용했을 경우, 메모리 누수가 발생할 수 있다.

unique_ptr<int[]>와 같이 템플릿에 배열로 정의해 주면, 소멸자로 delete[]를 호출할 수 있다.